/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 */

import path from 'path';

import { DependentModuleInfoV1, DependentModuleInfoV2 } from '@ohos/hvigor-arkts-compose';

import { getCurrentProductName } from '../../common/find-target-product.js';
import { ModuleTaskService } from '../../tasks/service/module-task-service.js';
import { ServiceLocator } from './service-locator.js';
import fse from 'fs-extra';
import { SdkInfo } from '../../sdk/sdk-info.js';

export class EvolutionService {
  protected dependentModuleMap: Map<string, DependentModuleInfoV1> = new Map<string, DependentModuleInfoV1>();

  addDependentModuleInfo(moduleName: string, moduleInfo: DependentModuleInfoV1) {
    this.dependentModuleMap.set(moduleName, moduleInfo);
  }

  initDependentModuleInfo(service: ModuleTaskService) {
    service!.getAllDependencies().forEach((dependency) => {
      if (dependency.isLocal()) {
        const targetService = ServiceLocator.getModulePathInfoServiceByProductAndModule(getCurrentProductName(), dependency.getModuleName());
        this.addDependentModuleInfo(dependency.getModuleName(),
          {
            language: ServiceLocator.getModuleLanuage(dependency.getModuleName()),
            packageName: dependency.getPackageName(),
            moduleName: dependency.getModuleName(),
            modulePath: dependency.getDependencyRootPath(),
            declgenV1OutPath: targetService?.getDeclgenV1OutPath() ?? '',
            declgenV2OutPath: targetService?.getDeclgenV2OutPath() ?? '',
            declgenBridgeCodePath: targetService?.getDeclgenBridgeCodePath() ?? '',
            declFilesPath: targetService?.getDeclFileInfoJsonPath() ?? '',
          });
      } else {
        const projectPath = service!.getProjectModel().getProjectDir();
        const declgenPath = path.resolve(projectPath, 'build', 'declgen', dependency.getPackageName());
        this.addDependentModuleInfo(dependency.getModuleName(),
          {
            language: service!.getDependencySelfArkTSVersion(dependency),
            packageName: dependency.getPackageName(),
            moduleName: dependency.getModuleName(),
            modulePath: dependency.getDependencyRootPath(),
            declgenV1OutPath: path.resolve(declgenPath, 'declgenV1'),
            declgenV2OutPath: path.resolve(declgenPath, 'declgenV2'),
            declgenBridgeCodePath: path.resolve(declgenPath, 'declgenBridgeCode'),
            declFilesPath: path.resolve(declgenPath, 'decl-fileInfo.json'),
          });
      }
    });
  }

  getDependentModuleInfoV1(service: ModuleTaskService, moduleName: string) {
    this.initDependentModuleInfo(service);
    return this.dependentModuleMap.get(moduleName)!;
  }

  async findFiles(dir: string, ignoreDirs: string[] = [], rootPath: string = dir, fileter: (file: string) => boolean) {
    const fileList: string[] = [];
    const files = await fse.readdir(dir);

    for (const file of files) {
      const filePath = path.join(dir, file);
      const stat = await fse.stat(filePath);

      if (stat.isDirectory()) {
        // 检查当前目录的完整路径是否包含忽略列表中的路径
        const normalizedPath = path.normalize(filePath);
        const shouldIgnore = ignoreDirs.some((ignoreDir) => {
          const normalizedIgnoreDir = path.normalize(path.resolve(rootPath, ignoreDir));
          return normalizedPath.includes(normalizedIgnoreDir);
        });

        if (shouldIgnore) {
          continue;
        }

        const subDirFiles = await this.findFiles(filePath, ignoreDirs, rootPath, fileter);
        fileList.push(...subDirFiles);
      } else if (stat.isFile() && !file.startsWith('BuildProfile') && fileter(file)) {
        fileList.push(filePath);
      }
    }
    return fileList;
  }

  async findEtsFiles(dir: string, ignoreDirs: string[] = [],
    rootPath: string = dir): Promise<string[]> {
    return await this.findFiles(dir, ignoreDirs, rootPath, (file: string) => file.endsWith('ets') && !file.endsWith('.d.ets'));
  }

  async findDeclgenFiles(dir: string, ignoreDirs: string[] = [],
    rootPath: string = dir): Promise<string[]> {
    return await this.findFiles(dir, ignoreDirs, rootPath, (file: string) => file.endsWith('.d.ets'));
  }

  /**
   * 获取编译所需的SDK路径
   * @param isHarmonyOS 是否为HarmonyOS工程
   * @protected
   */
  getLoadExternalApiPaths(isHarmonyOS: boolean, sdkInfo: SdkInfo): string[] {
    const externalApiPaths: string[] = [];
    externalApiPaths.push(...sdkInfo.getOpenHarmonyEtsV2ApiPaths());
    if (isHarmonyOS) {
      externalApiPaths.push(...sdkInfo.getHmsEtsV2ApiPaths());
    }
    return externalApiPaths;
  }
}